package GUI;
import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.openspaces.core.GigaSpace;
import org.openspaces.core.GigaSpaceConfigurer;
import org.openspaces.core.space.UrlSpaceConfigurer;
import org.openspaces.example.helloworld.common.Car;
import org.openspaces.example.helloworld.common.Direction;
import org.openspaces.example.helloworld.common.Roxel;
import org.openspaces.example.helloworld.common.StructureTuple;

import com.j_spaces.core.IJSpace;

import jgame.*;
import jgame.platform.*;

/** Tutorial example 7: Game states and timers.  Defines a simple game
 * state machine, with a title screen, start game, and in-game state.
 * Defines two timers, one ending the City_start state, and one shooting a
 * bullet from an object.
 */
public class City extends JGEngine {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	GigaSpace gigaSpace;
	
	public HashMap<Point,RoxelData> roxeldat;

	int noBlocksX = 5;
	int noBlocksY = 4;
	
	// in Block weidth/height in Roxel
	int blockWidth = 7;
	int blockHeight = 7;
	
	public static void main(String [] args) {
		new City(new JGPoint(640,480));
	}

	/** Application constructor. */
	public City(JGPoint size) { initEngine(size.x,size.y); }

	/** Applet constructor. */
	public City() { initEngineApplet(); }

	public void initCanvas() { setCanvasSettings(40,30,16,16,JGColor.black,new JGColor(0,140,0),null);}

	public void initGame() {
		setFrameRate(35,2);
		defineMedia("City_table.tbl");
		
		IJSpace space = new UrlSpaceConfigurer("jini://*/*/processorSpace").space();
		gigaSpace = new GigaSpaceConfigurer(space).gigaSpace();
		
		roxeldat = new HashMap<Point,RoxelData>();
		
		/**
		 * paint frame
		for(int i = 0; i <  (pfWidth()/16); i++){
			setTiles(i,0,new String[] { "h" });
		}
		
		for(int i = 0; i <  (pfWidth()/16); i++){
			setTiles(i,(pfHeight()/16)-1,new String[] { "#" });
		}
		for(int i = 0; i <  (pfHeight()/16); i++){
			setTiles(0,i,new String[] { "#" });
		}
		for(int i = 0; i <  (pfHeight()/16); i++){
			setTiles((pfWidth()/16)-1,i,new String[] { "#" });
		}
		 */
		setGameState("Title");
	}

	/**
	 * 
	 * redo with struct tupel
	 * @param blockx
	 * @param blocky
	 */
	public void initTileBlock(int blockx, int blocky){
		
		setTiles(7*blockx+1,7*blocky+1,new String[] { "hhhrhhh","hhhrhhh","hhhrhhh","rrrrrrr","hhhrhhh","hhhrhhh","hhhrhhh" });
	
	}
	
	public void clearTileBlock(int blockx, int blocky){
		for(int i = 0; i < blockWidth; i++){
			for(int j = 0; j < blockHeight; j++){
				setTiles(blockWidth*blockx+1+i,blockHeight*blocky+1+j,new String[] { "." });		
			}
		}
		
	}

	/* Title screen */

	/** Called when the Title state is entered. */
	public void startTitle() {
		// we need to remove all game objects when we go from in-game to the
		// title screen
		for(int i = 0; i < noBlocksX; i++){
			for(int j = 0; j < noBlocksY; j++){
				clearTileBlock(i,j);
			}
		}
		removeObjects(null,0);
		StructureTuple template = new StructureTuple();
		template.setProcessed(true);
		template = gigaSpace.read(template);
		this.blockHeight = template.getBlockLen();
		this.blockWidth = this.blockHeight;
		this.noBlocksX = template.getBlocksX();
		this.noBlocksY = template.getBlocksY();
		
		System.err.printf("blocks:x:%d y:%d  width:%d height %d\n",noBlocksX,noBlocksY,blockHeight,blockWidth);
	}

	public void paintFrameTitle() {
		drawString("Title state. Press space to go to City_view",pfWidth()/2,90,0);
	}

	public void doFrameTitle() {
		if (getKey(' ')) {
			// ensure the key has to be pressed again to register
			clearKey(' ');
			// Set both City_start and City_view states simultaneously.
			// When setting a state, the state becomes active only at the
			// beginning of the next frame.
			setGameState("City_start");
			
			// set a timer to remove the City_start state after a few seconds,
			// so only the City_view state remains.
			new JGTimer(
				40, // number of frames to tick until alarm
				true, // true means one-shot, false means run again
				      // after triggering alarm
				"City_start" // remove timer as soon as the City_start state
				            // is left by some other circumstance.
				            // In particular, if the game ends before
				            // the timer runs out, we don't want the timer to
				            // erroneously trigger its alarm at the next
				            // City_start.
			) {
				// the alarm method is called when the timer ticks to zero
				public void alarm() {
					addGameState("City_view");
					removeGameState("City_start");
				}
			};
		}
	}

	/** The City_start state is just for displaying a start message. */
	public void paintFrameCity_start() {
		drawString("We are in the City_start state.",pfWidth()/2,90,0);
		for(int i = 0; i < noBlocksX; i++){
			for(int j = 0; j < noBlocksY; j++){
				initTileBlock(i,j);
			}
		}
	}

	/** Called once when game goes into the City_view state. */
	public void startCity_view() {

	}

	public void paintFrameCity_view() {
		drawString("Press space to ESC to return to Title.",
			pfWidth()/2,150,0);
		
		
	    int blockCenter = blockWidth / 2;
	    if(!roxeldat.isEmpty()){
		    for(int bx = 0; bx < noBlocksX; bx++){
		    	for(int by = 0; by < noBlocksY; by++){
		    		for (int i = 0; i < blockWidth; i++) {
		    		    for (int j = 0; j < blockWidth; j++) {
		    			    if (i == blockCenter || j == blockCenter) {
		    			    	Point tmpP = new Point(bx*blockWidth+i+1,by*blockHeight+j+1);
		    			    	RoxelData tmpRox = roxeldat.get(tmpP);
		    			    	if(i == j && bx == 0 && by == 0){
		    			    		i = j;
		    			    	}
		    			    	if(tmpRox!=null && !tmpRox.occupied){
		    			    		setTiles(tmpP.x,tmpP.y,new String[] {"r"});
		    			    	}else{
		    			    		setTiles(tmpP.x,tmpP.y,new String[] {"c"});
		    			    	}
		    			    }
		    		    }
		    	    }
		    	}
		    }
	    }
	    roxeldat.clear();
	    
//		for(int i = 0; i < noBlocksX; i++){
//			for(int j = 0; j < noBlocksY; j++){
//				setTiles(7*i+1,7*j+1,new String[] { "hhhchhh","hhhchhh","hhhchhh","ccccccc","hhhchhh","hhhchhh","hhhchhh" });
//			}
//		}
		
//		if(!roxeldat.isEmpty()){
//			int tmp_size = roxeldat.size();
//			for(int i = 0; i < tmp_size; i++){
//				RoxelData tmp = roxeldat.get(i);
//				if(tmp.occupied){
//					setTiles(tmp.pos.x,tmp.pos.y,new String[] {"c"});
//				}else{
//					setTiles(tmp.pos.x,tmp.pos.y,new String[] {"r"});
//				}
//			}
//			roxeldat.clear();
//		}
	}

	// hilfmittel
	int framecnt = 0;
	
	public void doFrameCity_view() {
		moveObjects(null,0);
		// Space will get us back to the title screen.
		
		/**
		 * get positions of all cars and add to carpos List
		 * */
		Roxel template = new Roxel();
        template.setId(null);
        template.setOccupied(false);
		Roxel[] roxels = gigaSpace.readMultiple(template);
		for(int i = 0; i< roxels.length; i++){
			int posx = roxels[i].getTileCoords().x*this.blockWidth+roxels[i].getX()+1;
			int posy = roxels[i].getTileCoords().y*this.blockHeight+roxels[i].getY()+1;
			Point tmpP = new Point(posx,posy);
			roxeldat.put(tmpP,new RoxelData(tmpP,roxels[i].isOccupied()));
		}
		framecnt++;
		
		if (getKey(' ')) {
			// ensure the key has to be pressed again to register
			clearKey(' ');
			
			for(int i = 0; i < 10; i++){
				template = new Roxel();
		        template.setId(null);
		        template.setOccupied(false);
		        template.setXroads(false);
		        int xTile = (int)(Math.random()*noBlocksX);
		        int yTile = (int)(Math.random()*noBlocksY);
		        int xpos = (int)(Math.random()*blockWidth);
		        int ypos = (int)(Math.random()*blockHeight);
		        template.setTileCoords(new Point(xTile,yTile));
		        template.setX(xpos);
		        template.setY(ypos);
				template = gigaSpace.take(template);
	            if(template == null){
	            	continue;
	            }
				template.setOccupied(true);
	            if(template.getEast()){
	                template.setCar(new Car(Direction.EAST));
	            }else{
	                template.setCar(new Car(Direction.SOUTH));
	            }
	            if(template != null){
	            	System.out.println("adding Car");
	            	break;
	            }
			}
            gigaSpace.write(template);
		}
		
		if (getKey(27)) {
			// ensure the key has to be pressed again to register
			clearKey(27);
			// return to the Title state
			System.out.println("returning to title");
			setGameState("Title");
		}
		
		
	}

	class RoxelData{

		public Point pos;
		public boolean occupied;
		char dir;
		/** Constructor. */
		RoxelData () {	
			this.pos = new Point(0,0);
			this.occupied = false;
			this.dir = '-';
		}
		
		RoxelData (Point pos,boolean occupied) {	
			this.pos = pos;
			this.occupied = occupied;
			this.dir = '-';
		}
		
		RoxelData (int xpos, int ypos, boolean occupied) {	
			this.pos = new Point(xpos,ypos);
			this.occupied = occupied;
			this.dir = '-';
		}
		
		RoxelData (Point pos,boolean occupied, char direction) {	
			this.pos = new Point(0,0);
			this.occupied = occupied;
			this.dir = direction;
		}
		
		RoxelData (int xpos, int ypos, boolean occupied, char direction) {	
			this.pos = new Point(xpos,ypos);
			this.occupied = occupied;
			this.dir = direction;
		}

	} 

}
